package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.dto.CoursePubDTO;
import com.xuecheng.api.content.model.dto.CourseTeacherDTO;
import com.xuecheng.api.content.model.dto.TeachplanDTO;
import com.xuecheng.api.system.model.dto.CourseCategoryDTO;
import com.xuecheng.common.constant.ContentErrorCode;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseModeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.JsonUtil;
import com.xuecheng.content.agent.SystemApiAgent;
import com.xuecheng.content.common.constant.CoursePubTemplateKey;
import com.xuecheng.content.convert.CoursePubConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.entity.CoursePub;
import com.xuecheng.content.mapper.CoursePubMapper;
import com.xuecheng.content.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程发布 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CoursePubServiceImpl extends ServiceImpl<CoursePubMapper, CoursePub> implements CoursePubService {


    @Autowired
    private CourseBaseService courseBaseService;

    @Autowired
    private CourseMarketService courseMarketService;

    @Autowired
    private TeachplanService teachplanService;

    @Autowired
    private SystemApiAgent systemApiAgent;

    @Autowired
    private CourseTeacherService courseTeacherService;



    /*
     * 主方法业务：
     *   1.构建CoursePub数据并保存
     *
     *   2.根据CoursePub内容构架DataMap数据
     *
     *   3.将DataMap进行返回
     * */
    @Transactional
    public Map<String, Object> previewCourse(Long courseBaseId, Long companId) {

        //1.构建CoursePub数据并保存
        CoursePub coursePub = generateCoursePub(courseBaseId,companId);

        //根据CoursePub内容构架DateMap
        Map<String,Object> map = generateDateMap(coursePub);

        //3.将DateMap返回
        return map;
    }

    private Map<String, Object> generateDateMap(CoursePub coursePub) {

        // 1.构建数据模型对象
        HashMap<String, Object> dataMap = new HashMap<>();

        // 2.构建coursePub
        dataMap.put(CoursePubTemplateKey.COURSEPUB, coursePub);

        // 3.构建courseMarket
        String marketJsonString = coursePub.getMarket();
        CourseMarket courseMarket = JsonUtil.jsonToObject(marketJsonString, CourseMarket.class);

        dataMap.put(CoursePubTemplateKey.COURSEMARKET,courseMarket );

        // 4.构建课程计划
        String teachplanJsonString = coursePub.getTeachplan();
        TeachplanDTO teachplanDTO = JsonUtil.jsonToObject(teachplanJsonString, TeachplanDTO.class);
        dataMap.put(CoursePubTemplateKey.TEACHPLANNODE,teachplanDTO );

        String teacherJsonString = coursePub.getTeachers();
        CourseTeacherDTO courseTeacherDTO = JsonUtil.jsonToObject(teacherJsonString, CourseTeacherDTO.class);
        dataMap.put(CoursePubTemplateKey.COURSETEACHERS,courseTeacherDTO);

        // 5.构建课程模式
        CourseModeEnum[] values = CourseModeEnum.values();
        dataMap.put(CoursePubTemplateKey.COURSETEACHMODEENUMS,values );

        return dataMap;

    }

    /*
     * 构建CoursePub数据并保存
     *   业务分析：
     *       1.判断关键数据
     *        courseId companyId
     *       2.判断业务数据
     *           课程基础信息
     *               判断是否存在
     *               判断是否是同一家机构
     *               判断是否删除
     *               判断审核状态：教学机构课程预览--未提交、审核未通过
     *           课程营销
     *               判断是否存在：根据courseid
     *           课程计划
     *               获得课程计划：根据courseId和companyId（树形结构）
     *           课程教师
     *               判断教师信息是否存在：一定要确保课程最少有一个教师信息
     *
     *           课程分类数据并完善Coursepub数据
     *               调用system服务获得课程分类的名称
     *
     *       3.保存课程发布数据
     *           CoursePub数据保存数据库中
     *               课程基础信息  课程营销  课程计划  课程教师
     *
     *       4.将coursePub数据返回
     *
     * */
    private CoursePub generateCoursePub(Long courseBaseId, Long companId) {

//        1.判断关键数据
//        courseId companyId
//        2.判断业务数据
//                课程基础信息
//        判断是否存在
//                判断是否是同一家机构
//        判断是否删除
//        判断审核状态：教学机构课程预览--未提交、审核未通过

        //判断审核状态

        CourseBaseDTO courseBase = courseBaseService.getCourseBase(courseBaseId, companId);

        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }

        //课程营销
        //    判断是否存在：根据courseid

        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = new LambdaQueryWrapper<>();
        marketQueryWrapper.eq(CourseMarket::getCourseId,courseBaseId);

        CourseMarket market = courseMarketService.getOne(marketQueryWrapper);

        //课程计划
        //    获得课程计划：根据courseId和companyId（树形结构）

        TeachplanDTO teachplan = teachplanService.queryTeachplanById(courseBaseId, companId);
        //课程教师
        //    判断教师信息是否存在：一定要确保课程最少有一个教师信息

        List<CourseTeacherDTO> teacher = courseTeacherService.queryTeacherList(courseBaseId, companId);


        //课程分类数据并完善Coursepub数据
        //    调用system服务获得课程分类的名称
        String mt = courseBase.getMt();
        String st = courseBase.getSt();

        RestResponse<CourseCategoryDTO> mtResponse = systemApiAgent.getById(mt);

        if (!(mtResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(mtResponse.getCode(),mtResponse.getMsg());
        }

        RestResponse<CourseCategoryDTO> stRespones = systemApiAgent.getById(st);
        if (!(stRespones.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(stRespones.getCode(),stRespones.getMsg());
        }

        CourseCategoryDTO mtPo = mtResponse.getResult();
        CourseCategoryDTO stPo = stRespones.getResult();

        //构建coursePub数据并执行保存操作
        //课程基础数据

        CoursePub pubDTO = CoursePubConvert.INSTANCE.dto2vo(courseBase);

        //课程营销数据
        String marketjsontoString = JsonUtil.objectTojson(market);

        pubDTO.setMarket(marketjsontoString);
        pubDTO.setCharge(market.getCharge());
        pubDTO.setPrice(market.getPrice());

        //课程营销计划
        String teachplanJsonString = JsonUtil.objectTojson(teachplan);
        pubDTO.setTeachplan(teachplanJsonString);

        //教师信息
        String teacherJsonString = JsonUtil.objectTojson(teacher);
        pubDTO.setTeachers(teacherJsonString);

        //课程分类数据
        pubDTO.setMt(mtPo.getName());
        pubDTO.setSt(stPo.getName());


        //3.保存课程发布数据
        //    CoursePub数据保存数据库中
        //        课程基础信息  课程营销  课程计划  课程教师

        LambdaQueryWrapper<CoursePub> coursePubQueryWrapper = new LambdaQueryWrapper<>();
        coursePubQueryWrapper.eq(CoursePub::getCourseId,courseBaseId);
        coursePubQueryWrapper.eq(CoursePub::getCompanyId,companId);

        CoursePub coursePub = this.getOne(coursePubQueryWrapper);

        boolean result = false;
        //判断课程发布数据是否存在
        if (ObjectUtils.isEmpty(coursePub)) {
            //如果不存在
            //      创建课程发布数据
            //  创建课程发布数据时，要将coursePub和courseBase数据进行关联
            pubDTO.setCourseId(courseBase.getCourseBaseId());
            result = this.save(pubDTO);
        } else {
            //     如果存在
            //             修改课程发布数据内容

            pubDTO.setId(coursePub.getId());

            result = this.updateById(pubDTO);
        }

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120205);
        }

        return pubDTO;
    }
}
